import datetime
import re

from flask_jwt_extended import create_access_token
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename

from exts import db, oss, redis

from models import User
from utils import validate_url


def register(username, password, email, nickname):
    user = User.query.filter_by(username=username).first()
    if user:
        raise Exception("用户名已存在")

    if not re.findall(r"[a-zA-Z0-9_-]{6,18}", username):
        raise Exception("用户名不合法，长度应在6-18位之间，且只包含大小写字母与下划线")

    if not re.findall(r"[a-zA-Z0-9_-]{6,18}", password):
        raise Exception("密码不合法，长度应在6-18位之间，且只包含大小写字母与下划线")

    if not re.findall(r"[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+", email):
        raise Exception("邮箱格式不合法请检查")

    user = User(username=username,
                password=generate_password_hash(password),
                email=email,
                nickname=nickname,
                create_time=datetime.datetime.now(),
                update_time=datetime.datetime.now())

    db.session.add(user)

    try:
        db.session.commit()
        return True
    except Exception as ex:
        raise ex


def login(username, password):
    user = User.query.filter_by(username=username).first()

    if not user:
        raise Exception("用户名不存在")

    if not check_password_hash(user.password, password):
        raise Exception("密码不正确")

    access_token = create_access_token(identity={"username": username,
                                                 "user_id": user.user_id})

    redis.set(f"token:{access_token}", access_token, ex=60 * 60)

    return {"access_token": access_token}


def change_password(user_id, old_password, new_password, ver_password, token):
    user = User.query.filter_by(user_id=user_id).first()

    if not user:
        raise Exception("用户名不存在")

    if not check_password_hash(user.password, old_password):
        raise Exception("旧密码不正确")

    if new_password != ver_password:
        raise Exception("两次新密码不相同")

    if not re.findall(r"[a-zA-Z0-9_-]{6,18}", new_password):
        raise Exception("新密码不合法，长度应在6-18位之间，且只包含大小写字母与下划线")

    user.password = generate_password_hash(new_password)
    user.update_time = datetime.datetime.now()
    try:
        db.session.commit()
        redis.delete(f"token:{token}")
        return True
    except Exception as ex:
        raise ex


def get_user_list():
    user_list = User.query.all()
    user_list = [user.to_dict() for user in user_list]

    return user_list


def get_user_info(user_id):
    q = User.query.with_entities(User.username, User.email, User.nickname, User.create_time)
    user = q.filter_by(user_id=user_id).first()
    head = ['username', 'email', 'nickname', 'create_time']
    d = dict(zip(head, user))
    return d


def update_info(user_id, nickname, email):
    user = User.query.filter_by(user_id=user_id).first()

    if not user:
        raise Exception("用户名不存在")

    if nickname:
        if not re.findall(r".{1,255}", nickname):
            raise Exception("昵称不合法请检查，最长255字节")
        user.nickname = nickname

    if email:
        if not re.findall(r"[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+", email):
            raise Exception("邮箱格式不合法请检查")
        user.email = email

    user.update_time = datetime.datetime.now()

    try:
        db.session.commit()
        return True
    except Exception as ex:
        raise ex


def update_avatar(user_id, avatar):
    user = User.query.filter_by(user_id=user_id).first()

    if not user:
        raise Exception("用户名不存在")

    user.avatar = oss.upload_by_form(avatar)

    user.update_time = datetime.datetime.now()

    try:
        db.session.commit()
        return True
    except Exception as ex:
        raise ex
